<?php
/**
 * 网页爬虫类（城市学院用电查询系统）
 * @author Zeyes <lixize8888@163.com>
 * @link http://www.zeyes.org
 * @copyright (c) 2015-2017 DotTimes
 * @version 1.0
 */

class Crawler
{
    protected $dorm, $type = 2;
    private $elecaddr = '', $cookie=array(), $referer = '', $viewState = '', $validation="",$cookie_file;

    public function __construct($elecaddr="")
    {
        set_time_limit(0);
        if($elecaddr) $this->elecaddr = $elecaddr; else $this->elecaddr = '10.20.208.38:8089';
        $this->cookie_file = tempnam('./temp','cookie');
    }

    /**
     * 模拟请求网页
     * @param string    $url        请求的地址
     * @param array     $post_data  post数据，数组格式
     * @return string               返回网页数据
     */
    public function curl_request($url, $post_data=array('')) 
    {
        $ch = curl_init(); //初始化
        curl_setopt($ch, CURLOPT_HEADER, 1);
        // 如果你想把一个头包含在输出中，设置这个选项为一个非零值
        curl_setopt($ch, CURLOPT_URL, $url); //抓取指定网页
        //curl_setopt ($ch, CURLOPT_PROXY, '192.168.1.108:8888'); // 代理服务器，调试使用
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 不允许被抓取的链接跳转
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        if($this->referer)
            curl_setopt($ch, CURLOPT_REFERER, $this->referer);
        if(count($post_data))
        {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
        }
        curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookie_file); 
        curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie_file);
        curl_setopt($ch, CURLOPT_TIMEOUT, 8);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
        // 如果参数为1，成功只将结果返回，不自动输出返回的内容。如果失败返回FALSE，为0则相反
        $data = curl_exec($ch);
        if(curl_errno($ch))
        {
            return curl_error($ch);
        }
        curl_close($ch);

        //echo iconv("gb2312", "utf-8//IGNORE", $data);

        list($header, $body) = explode("\r\n\r\n", $data, 2);//分离header和body
        // 抓取VIEWSTATE和EVENTVALIDATION两个隐藏表单项的值
        {   
            $pattern = '/="__VIEWSTATE" value="(.*?)"/s';
            preg_match_all($pattern, $data, $matches);
            if(isset($matches[1][0]))
                $this->viewState = $matches[1][0];

            $pattern = '/="__EVENTVALIDATION" value="(.*?)"/s';
            preg_match_all($pattern, $data, $matches);
            if(isset($matches[1][0]))
                $this->validation = $matches[1][0];
        }

        //抓取Referer
        {
            preg_match_all("/Location: (.*?)\r\n/is", $header, $matches);
            if(isset($matches[1][0]))
            {
                $this->referer = 'http://'.$url.$matches[1][0];
            }
            else $this->referer = 'http://'.$url.'/';
        }
        
        return $body;
    }

    /**
     * 用电查询系统登录
     * @param string  $dorm   宿舍代码
     * @param int     $type   登录类型(默认2是查询用电，其他数字为查询充值情况)
     * @return boolean        返回是否登陆成功
     */
    public function elecLogin($dorm='', $type=2)
    {
        $this->type = $type;
        if($this->type == 2) $radio = 'usedR';
        else $radio = 'buyR';
        $this->dorm = $dorm;
        $page = $this->elecaddr;
        $result = $this->curl_request($page);
        $posts = array(
            '__EVENTTARGET'=>'drlouming',
            '__EVENTARGUMENT'=>'',
            '__LASTFOCUS'=>'',
            '__VIEWSTATE'=>$this->viewState,
            'drlouming'=>substr($this->dorm, 0, 2),
            'drceng'=>'',
            'drfangjian'=>''
            );
        $result = $this->curl_request($page, $posts);
        $posts['__EVENTTARGET'] = 'drceng';
        $posts['__VIEWSTATE'] = $this->viewState;
        $posts['drceng'] = substr($this->dorm, 0, 4);
        $result = $this->curl_request($page, $posts);
        $posts['__EVENTTARGET'] = '';
        $posts['__VIEWSTATE'] = $this->viewState;
        $posts['drfangjian'] = $this->dorm;
        $posts['radio'] = $radio;
        $posts['ImageButton1.x'] = rand(0, 90); // 点击的图片坐标位置
        $posts['ImageButton1.y'] = rand(0, 40);
        $result = $this->curl_request($page, $posts);

        //$result = iconv("gb2312", "utf-8//IGNORE", $result);
        preg_match("/退出/", $result, $matches);
        //var_dump($matches);
        if(isset($matches[0])) return true;
        else return false;
    }

    /**
     * 用电查询系统查询
     * @param string  $start   开始的时间, 例如2016-11-01
     * @param string  $end     结束的时间
     * @param int     $type   查询类型(默认2是查询用电，其他数字为查询充值情况)
     * @return array | boolean
     */
    public function queryRecord($start='2016-11-01', $end='')
    {
        if(2 == $this->type)$page = $this->elecaddr.'/usedRecord.aspx';
        else $page = $this->elecaddr.'/buyRecord.aspx';
        $posts = array(
            '__VIEWSTATE'=>$this->viewState,
            '__EVENTVALIDATION'=>$this->validation,
            'txtstart'=>$start,
            'txtend'=>$end,
            'btnser'=>''
            );
        $result = $this->curl_request($page, $posts);
        
        if(!empty($result))
        {
            $pattern = "/class=\"number\sorange\">(.*?)<\/span/s";
            preg_match_all($pattern, $result, $matches);
            if(isset($matches[1])) $info['overview'] = $matches[1];
            else $info['overview'] = array();
            if(2 == $this->type)
            {
                $pattern = "/class=\"contentLine\">\s*<td>(?<time>.*?)<\/td>\s*<td>(?<name>.*?)<\/td>\s*<td>(?<cost>.*?)<\/td>\s*<td>(?<price>.*?)<\/td>/is";
                preg_match_all($pattern, $result, $matches);
                $info['time'] = $matches['time'];
                $info['name'] = $matches['name'];
                $info['cost'] = $matches['cost'];
                $info['price'] = $matches['price'];
                $info['used'] = true;
            }
            else 
            {
                $pattern = "/class=\"contentLine\">\s*<td>(?<time>.*?)<\/td>\s*<td>(?<name>.*?)<\/td>\s*<td>(?<amount>.*?)<\/td>\s*<td>(?<advance>.*?)<\/td>\s*<td>(?<channel>.*?)<\/td>/is";
                preg_match_all($pattern, $result, $matches);
                $info['time'] = $matches['time'];
                $info['name'] = $matches['name'];
                $info['amount'] = $matches['amount'];
                $info['advance'] = $matches['advance'];
                $info['channel'] = $matches['channel'];
                $info['buy'] = true;
            }
            //var_dump($info);
            return $info;
        }
        return $info = false;
    }
};

//$elecUrl = '10.20.208.38:8089';
//$obj = new Crawler();
//$result = $obj->curl_request($elecUrl);
//$result = $obj->elecLogin('120411', 2);
//$result = $obj->queryRecord('2017-04-05', '2017-04-14', 2);
//var_dump($result);
?>